﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wolfpack.Core.Interfaces.Entities;
using System.Net.NetworkInformation;
using System.IO;
using System.Security.Cryptography.X509Certificates;


namespace Wolfpack.Contrib.Checks.Certificates
{
    //using System;
    //using System.Collections.Generic;
    //using System.Net.Security;
    //using System.Net.Sockets;
    //using System.Security.Cryptography.X509Certificates;
    //using System.Text.RegularExpressions;
    //using Wolfpack.Core;
    //using Wolfpack.Core.Checks;
    //using Wolfpack.Core.Interfaces.Entities;
    //using System.Net.NetworkInformation;
    //using System.IO;
    //using System.Security.Cryptography.X509Certificates;
    //using System;
    //using System.Collections.Generic;
    //using System.Net.Security;
    //using System;
    //using System.Diagnostics;
    //using System.IO;
    //using Wolfpack.Core;
    //using Wolfpack.Core.Interfaces;
    //using Wolfpack.Core.Interfaces.Entities;

    using System;
    using System.Diagnostics;
    using System.IO;
    using Wolfpack.Core;
    using Wolfpack.Core.Interfaces;
    using Wolfpack.Core.Interfaces.Entities;

    public class CertificateCheckConfig : PluginConfigBase
    {
        public String PublishOnlyOnFailure { get; set; }
        public String DaysOut { get; set; }
    }

    public class CertificateCheck : IHealthCheckPlugin
    {
        private readonly CertificateCheckConfig myConfig;
        private Boolean publishOnlyOnFailure;
        private int daysOut;

        public CertificateCheck(CertificateCheckConfig config)
        {
            myConfig = config;
            publishOnlyOnFailure = Boolean.Parse(myConfig.PublishOnlyOnFailure);
            daysOut = int.Parse(myConfig.DaysOut);
        }

        public Status Status { get; set; }

        public PluginDescriptor Identity
        {
            get
            {
                return new PluginDescriptor
                {
                    Description = "Checks Certificates",
                    Name = this.myConfig.FriendlyId,
                    TypeId = new Guid("0BA6FCD4-FB53-455e-B903-42A7722B4FA6")
                };
            }
        }

        /// <summary>
        /// Performs a one-time initialization.
        /// </summary>
        public void Initialise()
        {
        }

        public void Execute()
        {
            List<string> foundCerts = new List<string>();

            foreach (StoreName storeName in Enum.GetValues(typeof(StoreName)))
            {
                X509Store store = new X509Store(storeName, StoreLocation.LocalMachine);
                store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);

                X509Certificate2Collection certificates = store.Certificates.Find(
                    X509FindType.FindByTimeValid, DateTime.Now, true);

                if (certificates.Count != 0)
                {
                    foreach (X509Certificate2 certificate in certificates)
                    {
                        if (certificate.NotAfter.AddDays(daysOut) < DateTime.Now || publishOnlyOnFailure == false)
                        {
                            foundCerts.Add(certificate.FriendlyName);
                        }
                    }


                }

                store.Close();
            }

            if (foundCerts.Count > 0)
            {
                Publish(foundCerts);
            }

            Logger.Debug("Done checking for certificates.");
        }

        /// <summary>
        /// Sends information to the Wolfpack Publisher.  Usually this is a WCF publisher to a WCF activity to a SQL Server publisher.
        /// </summary>
        /// <param name="e">The event log entry to publish.</param>
        public void Publish(List<string> foundCerts)
        {
            try
            {
                var result = new HealthCheckData
                {
                    Identity = this.Identity,
                    Info = string.Format("CertificateCheck found a match."),
                    Result = false,
                    Tags = foundCerts.Count.ToString()
                };

                result.Properties = new ResultProperties();
                int certNum = 1;

                foreach (string cert in foundCerts)
                {
                    result.Properties.Add("FoundCert" + certNum.ToString(), cert);
                    certNum++;
                }

                Messenger.Publish(result);
            }
            catch (Exception ex)
            {
                Logger.Error("CertificateCheck error during publish: {0} ", ex.Message);
            }
        }
    }
}
